
/*
 * Copyright (C) 2008-2009 Archie L. Cobbs. All rights reserved.
 *
 * $Id: SimpleFieldModel.java 295 2010-01-13 21:03:17Z archie.cobbs $
 */

package org.dellroad.sidekar.schema.model;

import java.lang.reflect.Method;

import org.dellroad.sidekar.FieldType;

/**
 * Superclass for simple field types.
 */
public abstract class SimpleFieldModel extends FieldModel {

    private Method readMethod;
    private Method writeMethod;

    // Normal constructor
    SimpleFieldModel(String typeName) {
        super(typeName);
    }

    // Copy constructor
    SimpleFieldModel(SimpleFieldModel original) {
        super(original);
        this.readMethod = original.readMethod;
        this.writeMethod = original.writeMethod;
    }

    /**
     * Get the Java method used to read this field on the associated entity's class (i.e., the getter method).
     * This property is optional.
     */
    public Method getReadMethod() {
        return this.readMethod;
    }
    public void setReadMethod(Method readMethod) {
        this.readMethod = readMethod;
    }

    /**
     * Get the Java method used to write this field on the associated entity's class (i.e., the setter method).
     * This property is optional.
     */
    public Method getWriteMethod() {
        return this.writeMethod;
    }
    public void setWriteMethod(Method writeMethod) {
        this.writeMethod = writeMethod;
    }

    /**
     * Get a textual description of this field's type.
     *
     * <p>
     * This implementation just returns the type name. Subclasses should override
     * to provide type-specific details if necessary.
     */
    @Override
    public String getTypeDescription() {
        return this.typeName;
    }

    /**
     * This implementation does nothing, because simple fields may have a null name.
     * Subclasses should override as necessary.
     *
     * @param schema the schema being validated
     * @throws IllegalArgumentException if this field is invalid
     */
    @Override
    public void validate(SchemaModel schema) {
    }

    /**
     * Check whether the field name is (or isn't) null, and if not, validate the name.
     *
     * @param schema the schema being validated
     * @throws IllegalArgumentException if this field's name is invalid
     */
    public void validate(SchemaModel schema, boolean expectNull) {
        if (expectNull && getName() != null)
             throw new IllegalArgumentException("embedded field has a non-null name \"" + getName() + "\"");
        else if (!expectNull)
            super.validate(schema);
    }

    /**
     * Get the {@link SimpleFieldModel} type corresponding to the given Java class.
     *
     * @return the corresponding {@link SimpleFieldModel} class
     * @throws IllegalArgumentException if no such field model type exists
     */
    public static Class<? extends SimpleFieldModel> getModelType(Class<?> javaType) {
        try {
            return FieldType.forJavaType(javaType).getFieldModelType().asSubclass(SimpleFieldModel.class);
        } catch (ClassCastException e) {
            throw new IllegalArgumentException("no known simple field model type for " + javaType);
        }
    }
}

